जावास्क्रिप्ट इटरेटर हेल्पर्स प्रस्ताव स्ट्रीम फ्युजनद्वारे डेटा प्रोसेसिंगमध्ये कशी क्रांती घडवत आहे, इंटरमीडिएट अॅरे काढून टाकत आहे आणि लेझी इव्हॅल्युएशनद्वारे प्रचंड परफॉर्मन्स मिळवत आहे ते शोधा.
जावास्क्रिप्टच्या परफॉर्मन्समधील पुढील झेप: इटरेटर हेल्पर स्ट्रीम फ्युजनचा सखोल आढावा
सॉफ्टवेअर डेव्हलपमेंटच्या जगात, परफॉर्मन्सचा शोध हा एक अविरत प्रवास आहे. जावास्क्रिप्ट डेव्हलपर्ससाठी, .map(), .filter(), आणि .reduce() यांसारख्या अॅरे मेथड्सना एकत्र जोडून डेटा मॅनिप्युलेशन करणे ही एक सामान्य आणि सोपी पद्धत आहे. ही फ्लुएंट API वाचायला सोपी आणि अर्थपूर्ण आहे, परंतु ती एक मोठी परफॉर्मन्सची अडचण लपवते: इंटरमीडिएट अॅरे तयार करणे. साखळीतील प्रत्येक टप्प्यावर एक नवीन अॅरे तयार होतो, ज्यामुळे मेमरी आणि सीपीयू सायकल खर्च होतात. मोठ्या डेटासेटसाठी, ही एक मोठी परफॉर्मन्सची समस्या ठरू शकते.
येथे TC39 इटरेटर हेल्पर्स प्रस्तावाची एन्ट्री होते, जो ECMAScript स्टँडर्डमध्ये एक महत्त्वपूर्ण भर आहे आणि जावास्क्रिप्टमध्ये डेटा कलेक्शनवर प्रक्रिया करण्याची पद्धत बदलणार आहे. याच्या केंद्रस्थानी स्ट्रीम फ्युजन (किंवा ऑपरेशन फ्युजन) नावाचे एक शक्तिशाली ऑप्टिमायझेशन तंत्र आहे. हा लेख या नवीन पॅराडाइमचा सखोल आढावा देतो, ते कसे कार्य करते, ते महत्त्वाचे का आहे, आणि ते डेव्हलपर्सना अधिक कार्यक्षम, मेमरी-फ्रेंडली आणि शक्तिशाली कोड लिहिण्यास कसे सक्षम करेल हे स्पष्ट करतो.
पारंपारिक चेनिंगची समस्या: इंटरमीडिएट अॅरेची कहाणी
इटरेटर हेल्पर्सच्या नवीनतेचे पूर्ण कौतुक करण्यासाठी, आपल्याला आधी अॅरे-आधारित पद्धतीच्या मर्यादा समजून घेतल्या पाहिजेत. चला एक साधे, दैनंदिन काम विचारात घेऊया: संख्यांच्या सूचीमधून, आपल्याला पहिल्या पाच सम संख्या शोधायच्या आहेत, त्यांना दुप्पट करायचे आहे आणि निकाल गोळा करायचे आहेत.
पारंपारिक पद्धत
प्रमाणित अॅरे मेथड्स वापरून, कोड स्वच्छ आणि सहज समजण्यासारखा आहे:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ...]; // एक खूप मोठा अॅरे कल्पना करा
const result = numbers
.filter(n => n % 2 === 0) // पायरी १: सम संख्यांसाठी फिल्टर करा
.map(n => n * 2) // पायरी २: त्यांना दुप्पट करा
.slice(0, 5); // पायरी ३: पहिल्या पाच घ्या
हा कोड पूर्णपणे वाचनीय आहे, परंतु जावास्क्रिप्ट इंजिन पडद्याआड काय करते ते पाहूया, विशेषतः जर numbers मध्ये लाखो घटक असतील.
- पुनरावृत्ती १ (
.filter()): इंजिन संपूर्णnumbersअॅरेमधून जाते. ते मेमरीमध्ये एक नवीन इंटरमीडिएट अॅरे तयार करते, ज्याला आपणevenNumbersम्हणूया, ज्यात चाचणी उत्तीर्ण करणाऱ्या सर्व संख्या ठेवल्या जातात. जरnumbersमध्ये दहा लाख घटक असतील, तर हा सुमारे 500,000 घटकांचा अॅरे असू शकतो. - पुनरावृत्ती २ (
.map()): आता इंजिन संपूर्णevenNumbersअॅरेमधून जाते. ते एक दुसरा इंटरमीडिएट अॅरे तयार करते, ज्याला आपणdoubledNumbersम्हणूया, मॅपिंग ऑपरेशनचा निकाल साठवण्यासाठी. हा आणखी 500,000 घटकांचा अॅरे आहे. - पुनरावृत्ती ३ (
.slice()): शेवटी, इंजिनdoubledNumbersमधून पहिले पाच घटक घेऊन एक तिसरा, अंतिम अॅरे तयार करते.
लपलेला खर्च
ही प्रक्रिया अनेक गंभीर परफॉर्मन्स समस्या उघड करते:
- जास्त मेमरी वाटप: आम्ही दोन मोठे तात्पुरते अॅरे तयार केले जे लगेच टाकून दिले गेले. खूप मोठ्या डेटासेटसाठी, यामुळे मेमरीवर लक्षणीय ताण येऊ शकतो, ज्यामुळे अॅप्लिकेशन धीमे होऊ शकते किंवा क्रॅश देखील होऊ शकते.
- गार्बेज कलेक्शनचा ओव्हरहेड: तुम्ही जितके जास्त तात्पुरते ऑब्जेक्ट्स तयार करता, तितके गार्बेज कलेक्टरला त्यांना साफ करण्यासाठी जास्त काम करावे लागते, ज्यामुळे पॉज आणि परफॉर्मन्समध्ये अडथळे येतात.
- वाया गेलेली गणना: आम्ही लाखो घटकांवर अनेक वेळा पुनरावृत्ती केली. त्याहून वाईट म्हणजे, आमचे अंतिम ध्येय फक्त पाच निकाल मिळवणे होते. तरीही,
.filter()आणि.map()मेथड्सनी संपूर्ण डेटासेटवर प्रक्रिया केली,.slice()ने बहुतेक काम टाकून देण्यापूर्वी लाखो अनावश्यक गणना केली.
हीच मूळ समस्या आहे जी इटरेटर हेल्पर्स आणि स्ट्रीम फ्युजन सोडवण्यासाठी डिझाइन केले आहेत.
इटरेटर हेल्पर्सची ओळख: डेटा प्रोसेसिंगसाठी एक नवीन पॅराडाइम
इटरेटर हेल्पर्स प्रस्ताव Iterator.prototype मध्ये थेट अनेक परिचित मेथड्स जोडतो. याचा अर्थ असा की कोणताही ऑब्जेक्ट जो एक इटरेटर आहे (जनरेटर्स आणि Array.prototype.values() सारख्या मेथड्सच्या परिणामांसह) या शक्तिशाली नवीन साधनांमध्ये प्रवेश मिळवतो.
काही प्रमुख मेथड्समध्ये यांचा समावेश आहे:
.map(mapperFn).filter(filterFn).take(limit).drop(limit).flatMap(mapperFn).reduce(reducerFn, initialValue).toArray().forEach(fn).some(fn).every(fn).find(fn)
चला आपले पूर्वीचे उदाहरण या नवीन हेल्पर्सचा वापर करून पुन्हा लिहूया:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ...];
const result = numbers.values() // १. अॅरेमधून एक इटरेटर मिळवा
.filter(n => n % 2 === 0) // २. एक फिल्टर इटरेटर तयार करा
.map(n => n * 2) // ३. एक मॅप इटरेटर तयार करा
.take(5) // ४. एक टेक इटरेटर तयार करा
.toArray(); // ५. साखळी कार्यान्वित करा आणि निकाल गोळा करा
पहिल्या दृष्टीक्षेपात, कोड उल्लेखनीयपणे सारखा दिसतो. मुख्य फरक सुरुवातीच्या बिंदूत आहे—numbers.values()—जे अॅरेऐवजी एक इटरेटर परत करते, आणि टर्मिनल ऑपरेशन—.toArray()—जे अंतिम परिणाम तयार करण्यासाठी इटरेटरचा वापर करते. खरी जादू, तथापि, या दोन बिंदूंमध्ये काय घडते यात आहे.
ही साखळी कोणतेही इंटरमीडिएट अॅरे तयार करत नाही. त्याऐवजी, ती एक नवीन, अधिक गुंतागुंतीचा इटरेटर तयार करते जो मागील इटरेटरला गुंडाळतो. गणना स्थगित केली जाते. जोपर्यंत .toArray() किंवा .reduce() सारखी टर्मिनल मेथड व्हॅल्यूज वापरण्यासाठी बोलावली जात नाही तोपर्यंत काहीही होत नाही. या तत्त्वाला लेझी इव्हॅल्युएशन म्हणतात.
स्ट्रीम फ्युजनची जादू: एका वेळी एका घटकावर प्रक्रिया करणे
स्ट्रीम फ्युजन हे ते तंत्र आहे जे लेझी इव्हॅल्युएशनला इतके कार्यक्षम बनवते. संपूर्ण कलेक्शनवर वेगळ्या टप्प्यांत प्रक्रिया करण्याऐवजी, ते प्रत्येक घटकावर संपूर्ण ऑपरेशनच्या साखळीद्वारे वैयक्तिकरित्या प्रक्रिया करते.
असेम्ब्ली लाइनचे उदाहरण
एका उत्पादन कारखान्याची कल्पना करा. पारंपारिक अॅरे पद्धत प्रत्येक टप्प्यासाठी वेगळ्या खोल्या असण्यासारखी आहे:
- खोली १ (फिल्टरिंग): सर्व कच्चा माल (संपूर्ण अॅरे) आत आणला जातो. कामगार खराब माल फिल्टर करतात. चांगला माल एका मोठ्या डब्यात (पहिला इंटरमीडिएट अॅरे) ठेवला जातो.
- खोली २ (मॅपिंग): चांगल्या मालाचा संपूर्ण डबा पुढच्या खोलीत नेला जातो. येथे, कामगार प्रत्येक वस्तूमध्ये बदल करतात. बदललेल्या वस्तू दुसऱ्या मोठ्या डब्यात (दुसरा इंटरमीडिएट अॅरे) ठेवल्या जातात.
- खोली ३ (घेणे): दुसरा डबा शेवटच्या खोलीत नेला जातो, जिथे एक कामगार फक्त पहिल्या पाच वस्तू वरून घेतो आणि बाकीच्या टाकून देतो.
ही प्रक्रिया वाहतूक (मेमरी वाटप) आणि श्रम (गणना) या दोन्ही बाबतीत वायफळ आहे.
इटरेटर हेल्पर्सद्वारे चालणारे स्ट्रीम फ्युजन, एका आधुनिक असेम्ब्ली लाइनसारखे आहे:
- एकच कन्व्हेयर बेल्ट सर्व स्टेशनमधून जातो.
- एक वस्तू बेल्टवर ठेवली जाते. ती फिल्टरिंग स्टेशनवर जाते. जर ती अयशस्वी झाली, तर ती काढून टाकली जाते. जर ती पास झाली, तर ती पुढे जाते.
- ती लगेच मॅपिंग स्टेशनवर जाते, जिथे ती बदलली जाते.
- नंतर ती काउंटिंग स्टेशनवर (टेक) जाते. एक पर्यवेक्षक ती मोजतो.
- हे एका वेळी एका वस्तूसाठी चालू राहते, जोपर्यंत पर्यवेक्षक पाच यशस्वी वस्तू मोजत नाही. त्या क्षणी, पर्यवेक्षक "थांबा!" ओरडतो आणि संपूर्ण असेम्ब्ली लाइन बंद होते.
या मॉडेलमध्ये, इंटरमीडिएट उत्पादनांचे मोठे डबे नाहीत, आणि काम पूर्ण होताच लाइन थांबते. इटरेटर हेल्पर स्ट्रीम फ्युजन नेमके असेच कार्य करते.
एक-एक पायरीचे विश्लेषण
चला आपल्या इटरेटर उदाहरणाच्या अंमलबजावणीचा मागोवा घेऊया: numbers.values().filter(...).map(...).take(5).toArray().
.toArray()बोलावले जाते. त्याला एक व्हॅल्यू हवी आहे. ते त्याच्या स्रोताला,take(5)इटरेटरला, त्याच्या पहिल्या आयटमसाठी विचारते.take(5)इटरेटरला मोजण्यासाठी एक आयटम हवा आहे. ते त्याच्या स्रोताला,mapइटरेटरला, एका आयटमसाठी विचारते.mapइटरेटरला रूपांतरित करण्यासाठी एक आयटम हवा आहे. ते त्याच्या स्रोताला,filterइटरेटरला, एका आयटमसाठी विचारते.filterइटरेटरला चाचणीसाठी एक आयटम हवा आहे. ते मूळ अॅरे इटरेटरमधून पहिली व्हॅल्यू खेचते:1.- '1' चा प्रवास: फिल्टर
1 % 2 === 0तपासते. हे false आहे. फिल्टर इटरेटर1टाकून देतो आणि स्रोतामधून पुढील व्हॅल्यू खेचतो:2. - '2' चा प्रवास:
- फिल्टर
2 % 2 === 0तपासते. हे true आहे. ते2लाmapइटरेटरकडे पाठवते. mapइटरेटर2स्वीकारतो,2 * 2गणना करतो, आणि परिणाम,4,takeइटरेटरकडे पाठवतो.takeइटरेटर4स्वीकारतो. तो त्याचा अंतर्गत काउंटर कमी करतो (5 वरून 4) आणि4ला.toArray()कंझ्युमरला देतो. पहिला निकाल सापडला आहे.
- फिल्टर
toArray()कडे एक व्हॅल्यू आहे. तेtake(5)ला पुढील व्हॅल्यूसाठी विचारते. संपूर्ण प्रक्रिया पुन्हा होते.- फिल्टर
3(अयशस्वी), नंतर4(यशस्वी) खेचतो.4ला8मध्ये मॅप केले जाते, जे घेतले जाते. - हे तोपर्यंत चालू राहते जोपर्यंत
take(5)पाच व्हॅल्यूज देत नाही. पाचवी व्हॅल्यू मूळ संख्या10मधून असेल, जी20मध्ये मॅप केली जाईल. take(5)इटरेटरने पाचवी व्हॅल्यू देताच, त्याला कळते की त्याचे काम पूर्ण झाले आहे. पुढच्या वेळी जेव्हा त्याला व्हॅल्यूसाठी विचारले जाईल, तेव्हा तो संपल्याचा संकेत देईल. संपूर्ण साखळी थांबते.11,12, आणि मूळ अॅरेमधील इतर लाखो संख्यांकडे पाहिलेही जात नाही.
याचे फायदे प्रचंड आहेत: कोणतेही इंटरमीडिएट अॅरे नाहीत, किमान मेमरी वापर, आणि गणना शक्य तितक्या लवकर थांबते. ही कार्यक्षमतेतील एक मोठी क्रांती आहे.
व्यावहारिक अनुप्रयोग आणि परफॉर्मन्समधील वाढ
इटरेटर हेल्पर्सची शक्ती साध्या अॅरे मॅनिप्युलेशनच्या पलीकडे आहे. ते जटिल डेटा प्रोसेसिंगची कामे कार्यक्षमतेने हाताळण्यासाठी नवीन शक्यता उघडतात.
परिस्थिती १: मोठे डेटासेट आणि स्ट्रीम्सवर प्रक्रिया करणे
कल्पना करा की तुम्हाला मल्टी-गिगाबाइट लॉग फाइल किंवा नेटवर्क सॉकेटमधून येणाऱ्या डेटाच्या स्ट्रीमवर प्रक्रिया करायची आहे. संपूर्ण फाइल मेमरीमधील अॅरेमध्ये लोड करणे अनेकदा अशक्य असते.
इटरेटर्ससह (आणि विशेषतः असिंक इटरेटर्स, ज्यावर आपण नंतर चर्चा करू), तुम्ही डेटा तुकड्या-तुकड्याने प्रक्रिया करू शकता.
// मोठ्या फाईलमधून ओळी देणाऱ्या जनरेटरचे संकल्पनात्मक उदाहरण
function* readLines(filePath) {
// फाईल पूर्ण लोड न करता ओळी-ओळीने वाचणारी अंमलबजावणी
// yield line;
}
const errorCount = readLines('huge_app.log').values()
.map(line => JSON.parse(line))
.filter(logEntry => logEntry.level === 'error')
.take(100) // पहिल्या 100 त्रुटी शोधा
.reduce((count) => count + 1, 0);
या उदाहरणात, फाईलची केवळ एक ओळ पाइपलाइनमधून जाताना एका वेळी मेमरीमध्ये राहते. प्रोग्राम कमीत कमी मेमरी फूटप्रिंटसह टेराबाइट्स डेटावर प्रक्रिया करू शकतो.
परिस्थिती २: लवकर समाप्ती आणि शॉर्ट-सर्किटिंग
हे आपण आधीच .take() सह पाहिले आहे, परंतु ते .find(), .some(), आणि .every() सारख्या मेथड्सना देखील लागू होते. मोठ्या डेटाबेसमधून पहिला प्रशासक (administrator) वापरकर्ता शोधण्याचा विचार करा.
अॅरे-आधारित (अकार्यक्षम):
const firstAdmin = users.filter(u => u.isAdmin)[0];
येथे, .filter() संपूर्ण users अॅरेवर पुनरावृत्ती करेल, जरी पहिलाच वापरकर्ता प्रशासक असला तरी.
इटरेटर-आधारित (कार्यक्षम):
const firstAdmin = users.values().find(u => u.isAdmin);
.find() हेल्पर प्रत्येक वापरकर्त्याची एक-एक करून चाचणी करेल आणि पहिला जुळणारा सापडताच संपूर्ण प्रक्रिया त्वरित थांबवेल.
परिस्थिती ३: अनंत अनुक्रमांसह काम करणे
लेझी इव्हॅल्युएशनमुळे संभाव्यतः अनंत डेटा स्रोतांसह काम करणे शक्य होते, जे अॅरेसह अशक्य आहे. जनरेटर अशा अनुक्रम तयार करण्यासाठी योग्य आहेत.
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
// 1000 पेक्षा मोठ्या पहिल्या 10 फिबोनाची संख्या शोधा
const result = fibonacci()
.filter(n => n > 1000)
.take(10)
.toArray();
// result will be [1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393]
हा कोड उत्तम प्रकारे चालतो. fibonacci() जनरेटर कायम चालू शकतो, परंतु ऑपरेशन्स लेझी असल्यामुळे आणि .take(10) एक थांबण्याची अट प्रदान करत असल्यामुळे, प्रोग्राम विनंती पूर्ण करण्यासाठी आवश्यक तितक्याच फिबोनाची संख्यांची गणना करतो.
व्यापक इकोसिस्टमवर एक नजर: असिंक इटरेटर्स
या प्रस्तावाचे सौंदर्य हे आहे की ते केवळ सिंक्रोनस इटरेटर्सना लागू होत नाही. ते AsyncIterator.prototype वर असिंक इटरेटर्ससाठी हेल्पर्सचा एक समांतर संच देखील परिभाषित करते. आधुनिक जावास्क्रिप्टसाठी हे एक गेम-चेंजर आहे, जिथे असिंक्रोनस डेटा स्ट्रीम्स सर्वव्यापी आहेत.
एका पेजिनेटेड API वर प्रक्रिया करणे, Node.js मधून फाइल स्ट्रीम वाचणे, किंवा WebSocket मधून डेटा हाताळणे याची कल्पना करा. हे सर्व नैसर्गिकरित्या असिंक स्ट्रीम्स म्हणून प्रस्तुत केले जातात. असिंक इटरेटर हेल्पर्ससह, तुम्ही त्यांच्यावर समान घोषणात्मक .map() आणि .filter() सिंटॅक्स वापरू शकता.
// पेजिनेटेड API वर प्रक्रिया करण्याचे संकल्पनात्मक उदाहरण
async function* fetchAllUsers() {
let url = '/api/users?page=1';
while (url) {
const response = await fetch(url);
const data = await response.json();
for (const user of data.users) {
yield user;
}
url = data.nextPageUrl;
}
}
// एका विशिष्ट देशातील पहिले 5 सक्रिय वापरकर्ते शोधा
const activeUsers = await fetchAllUsers()
.filter(user => user.isActive)
.filter(user => user.country === 'DE')
.take(5)
.toArray();
हे जावास्क्रिप्टमध्ये डेटा प्रोसेसिंगसाठी प्रोग्रामिंग मॉडेलला एकत्रित करते. तुमचा डेटा साध्या इन-मेमरी अॅरेमध्ये असो किंवा रिमोट सर्व्हरवरून असिंक्रोनस स्ट्रीममध्ये, तुम्ही समान शक्तिशाली, कार्यक्षम आणि वाचनीय पॅटर्न्स वापरू शकता.
सुरुवात करणे आणि सद्यस्थिती
२०२४ च्या सुरुवातीस, इटरेटर हेल्पर्स प्रस्ताव TC39 प्रक्रियेच्या स्टेज ३ वर आहे. याचा अर्थ डिझाइन पूर्ण झाले आहे, आणि समितीला अपेक्षा आहे की ते भविष्यातील ECMAScript स्टँडर्डमध्ये समाविष्ट केले जाईल. ते आता प्रमुख जावास्क्रिप्ट इंजिनमध्ये अंमलबजावणी आणि त्या अंमलबजावणींकडून अभिप्रायाची वाट पाहत आहे.
आज इटरेटर हेल्पर्स कसे वापरावे
- ब्राउझर आणि Node.js रनटाइम्स: प्रमुख ब्राउझर्सच्या (जसे की Chrome/V8) आणि Node.js च्या नवीनतम आवृत्त्या या वैशिष्ट्यांची अंमलबजावणी करण्यास सुरुवात करत आहेत. त्यांना मूळतः वापरण्यासाठी तुम्हाला विशिष्ट फ्लॅग सक्षम करण्याची किंवा अगदी अलीकडील आवृत्ती वापरण्याची आवश्यकता असू शकते. नेहमी नवीनतम सुसंगतता सारण्या तपासा (उदा. MDN किंवा caniuse.com वर).
- पॉलीफिल्स: जुन्या रनटाइम्सना समर्थन देण्याची आवश्यकता असलेल्या प्रोडक्शन वातावरणासाठी, तुम्ही पॉलीफील वापरू शकता. सर्वात सामान्य मार्ग
core-jsलायब्ररीद्वारे आहे, जी अनेकदा Babel सारख्या ट्रान्सपाइलर्सद्वारे समाविष्ट केली जाते. Babel आणिcore-jsकॉन्फिगर करून, तुम्ही इटरेटर हेल्पर्स वापरून कोड लिहू शकता आणि त्याला जुन्या वातावरणात काम करणाऱ्या समतुल्य कोडमध्ये रूपांतरित करू शकता.
निष्कर्ष: जावास्क्रिप्टमध्ये कार्यक्षम डेटा प्रोसेसिंगचे भविष्य
इटरेटर हेल्पर्स प्रस्ताव केवळ नवीन मेथड्सचा संच नाही; ते जावास्क्रिप्टमध्ये अधिक कार्यक्षम, स्केलेबल आणि अर्थपूर्ण डेटा प्रोसेसिंगकडे एक मूलभूत बदल दर्शवते. लेझी इव्हॅल्युएशन आणि स्ट्रीम फ्युजन स्वीकारून, ते मोठ्या डेटासेटवर अॅरे मेथड्स चेनिंगशी संबंधित दीर्घकाळच्या परफॉर्मन्स समस्यांचे निराकरण करते.
प्रत्येक डेव्हलपरसाठी मुख्य मुद्दे आहेत:
- डीफॉल्टनुसार परफॉर्मन्स: इटरेटर मेथड्स चेनिंग केल्याने इंटरमीडिएट कलेक्शन टाळले जातात, ज्यामुळे मेमरी वापर आणि गार्बेज कलेक्टरचा भार लक्षणीयरीत्या कमी होतो.
- आळशीपणासह वर्धित नियंत्रण: गणना केवळ आवश्यक असेल तेव्हाच केली जाते, ज्यामुळे लवकर समाप्ती आणि अनंत डेटा स्रोतांचे सुरेख हाताळणी शक्य होते.
- एक एकीकृत मॉडेल: समान शक्तिशाली पॅटर्न सिंक्रोनस आणि असिंक्रोनस दोन्ही डेटावर लागू होतात, ज्यामुळे कोड सोपा होतो आणि जटिल डेटा प्रवाहांबद्दल तर्क करणे सोपे होते.
हे वैशिष्ट्य जावास्क्रिप्ट भाषेचा एक मानक भाग बनल्यामुळे, ते परफॉर्मन्सचे नवीन स्तर अनलॉक करेल आणि डेव्हलपर्सना अधिक मजबूत आणि स्केलेबल अॅप्लिकेशन्स तयार करण्यास सक्षम करेल. आता स्ट्रीम्समध्ये विचार करण्याची आणि तुमच्या करिअरमधील सर्वात कार्यक्षम डेटा-प्रोसेसिंग कोड लिहिण्यासाठी तयार होण्याची वेळ आली आहे.